package com.github.lee.mvvm.core.ui

import android.os.Bundle
import android.view.View
import android.view.Window
import android.widget.FrameLayout
import android.widget.Toast
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.annotation.IntRange
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import com.github.lee.mvvm.core.R
import com.github.lee.mvvm.core.databinding.LayoutBaseHoverBinding
import com.github.lee.mvvm.core.databinding.LayoutBaseLinearBinding
import com.github.lee.mvvm.core.util.viewGone
import com.github.lee.mvvm.core.vm.BaseViewModel
import qiu.niorgai.StatusBarCompat

abstract class BaseActivity<VB : ViewDataBinding, VM : BaseViewModel> : AppCompatActivity() {

    protected val mContext by lazy { this }
    protected var isToolbarHover = false

    protected lateinit var rootVB: ViewDataBinding

    protected var loadingView: View? = null
    protected var pageVB: VB? = null
    protected var emptyView: View? = null
    protected var errorView: View? = null

    protected lateinit var pageVM: VM


    //===Desc:=========================================================

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        onInitData(savedInstanceState)
        pageVM = onCreateViewModel()
        lifecycle.addObserver(pageVM)
        if (isFinishing) {
            return
        }
        //请求隐藏Actionbar
        requestWindowFeature(Window.FEATURE_NO_TITLE)
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
        rootVB = if (isToolbarHover) {
            LayoutBaseHoverBinding.inflate(layoutInflater)
                .also {
                    it.lifecycleOwner = this
                    showLayout(it.flBaseToolbarContainer, it.flBaseContentContainer)
                    setContentView(it.root)
                }
        } else {
            LayoutBaseLinearBinding.inflate(layoutInflater)
                .also {
                    it.unbind()
                    it.lifecycleOwner = this
                    showLayout(it.flBaseToolbarContainer, it.flBaseContentContainer)
                    setContentView(it.root)
                }
        }
        rootVB.lifecycleOwner = this
        onObserveData()
        if (null != loadingView) {
            pageVM.uiObserve.postValue(BaseViewModel.UiModel.loading())
        } else {
            if (null != pageVB) {
                pageVM.uiObserve.postValue(BaseViewModel.UiModel.success())
            }
        }
        onSetViewListener()
        onSetViewData()
    }

    override fun onDestroy() {
        super.onDestroy()
        rootVB.unbind()
        pageVB?.unbind()
    }
    //===Desc:=========================================================

    private fun showLayout(toolbarContainer: FrameLayout, contentContainer: FrameLayout) {
        onCreateToolbar().apply {
            if (null != this) {
                toolbarContainer.removeAllViews()
                setSupportActionBar(this)
                toolbarContainer.addView(this)
                viewGone(toolbarContainer, false)
            } else {
                viewGone(toolbarContainer, true)
            }
        }

        onCreateLoading().apply {
            loadingView = this
            if (null != this) {
                contentContainer.addView(this)
                viewGone(this, true)
            }
        }

        pageVB?.apply {
            this.lifecycleOwner = this@BaseActivity
            contentContainer.addView(this.root)
            viewGone(this.root, true)
        }

        onCreateSuccess().apply {
            pageVB = this
            if (null != this) {
                this.lifecycleOwner = this@BaseActivity
                contentContainer.addView(this.root)
                viewGone(this.root, true)
            }
        }

        onCreateEmpty().apply {
            emptyView = this
            if (null != this) {
                contentContainer.addView(this)
                viewGone(this, true)
            }
        }

        onCreateError().apply {
            errorView = this
            if (null != this) {
                contentContainer.addView(this)
                viewGone(this, true)
            }
        }
    }


    //===Desc:=========================================================

    protected open fun onInitData(savedInstanceState: Bundle?) {}
    protected open fun onObserveData() {
        pageVM.uiObserve.observe(this) {
            if (null == it) {
                return@observe
            }
            when (it.pageEvent) {
                BaseViewModel.PageEvent.LOADING -> {
                    if (null != loadingView) {
                        viewGone(loadingView, false)
                        viewGone(pageVB?.root, true)
                        viewGone(emptyView, true)
                        viewGone(errorView, true)
                    }
                }
                BaseViewModel.PageEvent.SUCCESS -> {
                    if (null != pageVB) {
                        viewGone(loadingView, true)
                        viewGone(pageVB?.root, false)
                        viewGone(emptyView, true)
                        viewGone(errorView, true)
                    }
                }
                BaseViewModel.PageEvent.EMPTY -> {
                    if (null != emptyView) {
                        viewGone(loadingView, true)
                        viewGone(pageVB?.root, true)
                        viewGone(emptyView, false)
                        viewGone(errorView, true)
                    }
                    onUiStateEmptyOrError(true, it.icon, it.msg)
                }
                BaseViewModel.PageEvent.ERROR -> {
                    if (null != errorView) {
                        viewGone(loadingView, true)
                        viewGone(pageVB?.root, true)
                        viewGone(emptyView, true)
                        viewGone(errorView, false)
                    }
                    onUiStateEmptyOrError(false, it.icon, it.msg)
                }
                BaseViewModel.PageEvent.WAIT -> {
                    //显示加载中
                }
                BaseViewModel.PageEvent.TOAST -> {
                    if (it.msg.isNotEmpty()) {
                        Toast.makeText(mContext, it.msg, Toast.LENGTH_SHORT)
                            .show()
                    }
                }
            }
        }
    }

    protected open fun onSetViewListener() {}
    protected open fun onSetViewData() {}

    //===Desc:=========================================================

    protected abstract fun onCreateViewModel(): VM

    protected open fun onCreateToolbar(): Toolbar? = null
    protected open fun onCreateLoading(): View? = null
    protected open fun onCreateSuccess(): VB? = null
    protected open fun onCreateEmpty(): View? = null
    protected open fun onCreateError(): View? = null

    //===Desc:=========================================================

    protected open fun onUiStateEmptyOrError(
        isEmpty: Boolean,
        @DrawableRes icon: Int = -1,
        msg: String = ""
    ) {
    }

    //===Desc:状态栏相关=========================================================
    protected fun setStatusBarColor(
        @ColorInt color: Int,
        @IntRange(from = 0, to = 255) alpha: Int? = null
    ) {
        if (null == alpha) {
            StatusBarCompat.setStatusBarColor(this, color)
        } else {
            StatusBarCompat.setStatusBarColor(this, color, alpha)
        }
    }

    protected fun translucentStatusBar(hideStatusBarBackground: Boolean = false) {
        StatusBarCompat.translucentStatusBar(this, hideStatusBarBackground)
    }

    protected fun changeStatusBarTextColor(isBlack: Boolean) {
        if (isBlack) {
            StatusBarCompat.changeToLightStatusBar(this)
        } else {
            StatusBarCompat.cancelLightStatusBar(this)
        }
    }


    protected fun replaceFragment(f: Fragment) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.fl_base_content_container, f)
            .commitNowAllowingStateLoss()
    }

}